package baiqitun.stupro.common.aspect;

import baiqitun.stupro.common.entity.impl.SysLog;
import baiqitun.stupro.common.service.system.SysLogService;
import baiqitun.stupro.common.util.AuthUtil;
import io.swagger.models.HttpMethod;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;

/**
 * 日志切面
 * @author kedaji
 */
@Component
@Aspect
public class LogAspect {
    @Autowired
    private SysLogService sysLogService;

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void getRequestLogPointCut() {
    }
    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void postRequestLogPointCut() {
    }
    @Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
    public void putRequestLogPointCut() {
    }
    @Pointcut("@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public void deleteRequestLogPointCut() {
    }

    @Around("getRequestLogPointCut()")
    private Object getRequestAround(ProceedingJoinPoint point) throws Throwable{
        return exec(point, HttpMethod.GET);
    }
    @Around("postRequestLogPointCut()")
    private Object postRequestAround(ProceedingJoinPoint point) throws Throwable{
        return exec(point, HttpMethod.POST);
    }
    @Around("putRequestLogPointCut()")
    private Object putRequestAround(ProceedingJoinPoint point) throws Throwable{
        return exec(point, HttpMethod.PUT);
    }
    @Around("deleteRequestLogPointCut()")
    private Object deleteRequestAround(ProceedingJoinPoint point) throws Throwable{
        return exec(point, HttpMethod.DELETE);
    }

    private Object exec(ProceedingJoinPoint point, HttpMethod httpMethod) throws Throwable {
        long start = System.currentTimeMillis();;
        try {
            Object result = point.proceed();
            return result;
        } catch (Throwable e){
            throw e;
        } finally {
            long castTime = System.currentTimeMillis() - start;
            saveLog(castTime, httpMethod);
        }
    }


    private void saveLog(Long time, HttpMethod httpMethod){
        SysLog sysLog = new SysLog();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        sysLog.setCreateBy(AuthUtil.getUsername(authentication));
        sysLog.setCastTime(time).setUri(request.getRequestURI()).setMethod(httpMethod.name()).setIp(request.getRemoteAddr()).setParameter(request.getParameterMap());;
        sysLogService.save(sysLog);
    }
}
